package com.bnd.controller;

import cn.hutool.core.util.StrUtil;
import com.alibaba.dashscope.aigc.generation.Generation;
import com.alibaba.dashscope.aigc.generation.GenerationParam;
import com.alibaba.dashscope.aigc.generation.GenerationResult;
import com.alibaba.dashscope.common.Message;
import com.alibaba.dashscope.common.Role;
import com.bnd.common.BaseResponse;
import com.bnd.common.ErrorCode;
import com.bnd.common.ResultUtils;
import com.bnd.common.SafetyMessage;
import com.bnd.common.manager.GenericChatSessionManager;
import com.bnd.config.AiConfig;
import com.bnd.config.SseEmitterUTF8;
import com.bnd.domain.ChatHistory;
import com.bnd.domain.session.ChatSession;
import com.bnd.service.*;
import com.bnd.utils.ThrowUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * 角色对话控制器
 */
@Slf4j
@RestController
@RequestMapping("/roleChat")
public class RolePlayController {
    @Resource
    private RoleChatService roleChatService;
    @Resource
    private ImageService imageService;
    @Resource
    private AiConfig aiConfig;
    @Resource
    private ContentSafetyService contentSafetyService;
    @Resource
    private ChatHistoryService chatHistoryService;
    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
    @Resource(name = "chatSessionManager")
    private GenericChatSessionManager<ChatSession> chatSessionManager;

    /**
     * 流式对话接口（SSE）
     * @param userInput 用户输入内容
     * @param chatId 聊天会话ID
     * @param characterId 角色ID
     * @return SSE流式响应
     */
    @GetMapping("/streamChat")
    public SseEmitter doStreamChat(String userInput, String chatId, Long characterId){
        ThrowUtils.throwIf(StrUtil.hasBlank(userInput, chatId) || characterId == null, ErrorCode.SYSTEM_ERROR, "参数错误！");

        // 用户输入敏感词校验
        log.info("[SSE][输入校验] chatId={}, characterId={}, 入参长度={}, 预览='{}'", chatId, characterId, (userInput == null ? 0 : userInput.length()), StrUtil.subPre(userInput, 50));
        String bad = contentSafetyService == null ? null : contentSafetyService.checkText(userInput);
        log.info("[SSE][输入校验结果] chatId={}, bad={}", chatId, bad);
        if (bad != null) {
            SseEmitter emitter = new SseEmitterUTF8(10000L);
            try { emitter.send(SseEmitter.event().name("error").data(SafetyMessage.BLOCKED_REPLY)); } catch (Exception ignore) {}
            try { emitter.complete(); } catch (Exception ignore) {}

            return emitter;
        }

        ChatSession session = chatSessionManager.getOrCreate(chatId, characterId, id -> new ChatSession(id, characterId, null));
        // 关键：每次会话轮次都需要一个全新的 SseEmitter，避免复用已完成的连接
        session.setSseEmitter(new SseEmitterUTF8(180000L));

        StreamChatHandle handle = roleChatService.doStreamChatDeferComplete(userInput, session);
        SseEmitter emitter = handle.getEmitter();

        AtomicBoolean open = new AtomicBoolean(true);
        emitter.onCompletion(() -> { open.set(false); log.info("[SSE] 连接完成 chatId={}", chatId); });
        emitter.onTimeout(() -> { open.set(false); log.warn("[SSE] 连接超时 chatId={}", chatId); });
        emitter.onError(e -> { open.set(false); log.error("[SSE] 连接错误 chatId={}", chatId, e); });

        //构建用户消息
        List<ChatHistory> historyList = new ArrayList<>(2);
        ChatHistory userChat = new ChatHistory();
        userChat.setRole("0");
        userChat.setContent(userInput);
        userChat.setChatId(chatId);
        userChat.setCharacterId(characterId);
        historyList.add(userChat);

        // 文本完成后再决定是否触发文生图，然后最后complete
        handle.getTextDoneFuture().whenCompleteAsync((text, err) -> {
            if (err != null) {
                log.error("文本生成失败，跳过文生图", err);
                try { if (open.get()) emitter.completeWithError(err); } catch (Exception ignore) {}
                return;
            }
            try {
                // AI输出敏感词校验
                log.info("[SSE][输出校验] chatId={}, 文本长度={}, 预览='{}'", chatId, (text == null ? 0 : text.length()), StrUtil.subPre(text, 50));
                String outBad = contentSafetyService == null ? null : contentSafetyService.checkText(text);
                log.info("[SSE][输出校验结果] chatId={}, bad={}", chatId, outBad);
                if (outBad != null) {
                    if (open.get()) {
                        emitter.send(SseEmitter.event().name("error").data("AI输出包含敏感内容，已拦截"));
                    }
                    return;
                }
                StructuredReply reply = judgeNeedImage(userInput);
                ChatHistory assistantChat = new ChatHistory();
                
                // 立即通知前端文生图状态
                try {
                    if (open.get()) {
                        Map<String, Object> imageStatus = new HashMap<>();
                        imageStatus.put("needImage", Boolean.TRUE.equals(reply.needImage));
                        if (Boolean.TRUE.equals(reply.needImage) && StrUtil.isNotBlank(reply.imagePrompt)) {
                            imageStatus.put("imagePrompt", reply.imagePrompt);
                        }
                        emitter.send(SseEmitter.event().name("imageStatus").data(imageStatus));
                    }
                } catch (Exception e) {
                    log.warn("[SSE] 发送文生图状态失败", e);
                }
                
                if (Boolean.TRUE.equals(reply.needImage) && StrUtil.isNotBlank(reply.imagePrompt)) {
                    log.info("[文生图触发] chatId={}, prompt={}", chatId, StrUtil.subPre(reply.imagePrompt, 200));
                    List<String> urls = imageService.textToImage(reply.imagePrompt, "1024*1024", 1);
                    if (urls != null && !urls.isEmpty()) {
                        //默认只存第一张图片
                        assistantChat.setImageUrl(urls.get(0));
                        try {
                            if (open.get()) {
                                emitter.send(SseEmitter.event().name("image").data(urls.get(0)));
                            } else {
                                log.warn("[SSE] 连接已关闭，图片发送被跳过 chatId={}", chatId);
                            }
                        } catch (Exception sendEx) {
                            log.error("SSE发送图片URL数组失败", sendEx);
                        }
                    } else {
                        log.warn("[文生图触发] 未获取到图片地址");
                    }
                }

                //构建assistant消息
                if (StrUtil.isNotBlank(text)){
                    assistantChat.setRole("1");
                    assistantChat.setContent(text);
                    assistantChat.setChatId(chatId);
                    assistantChat.setCharacterId(characterId);
                    historyList.add(assistantChat);
                }
                //持久化对话内容
                chatHistoryService.saveBatch(historyList);
                //删除缓存
                chatHistoryService.clearChatHistoryCache(characterId);
            } catch (Exception e) {
                log.error("文生图判断或生成失败", e);
            } finally {
                try {
                    if (open.get()) {
                        log.info("[SSE] 完成并关闭连接 chatId={}", chatId);
                        emitter.complete();
                    }
                } catch (Exception ignore) {}
            }
        });

        return emitter;
    }

    private static class StructuredReply {
        public String text;
        public Boolean needImage;
        public String imagePrompt;
    }

    /**
     * 判断用户输入是否需要生成图片
     * @param userInput 用户输入内容
     * @return 结构化回复，包含是否需要图片及图片提示词
     */
    private StructuredReply judgeNeedImage(String userInput) {
        try {
            String judgeSystem = "你是一个助手。根据用户输入，判断是否需要生成一张图片。严格只输出如下JSON：\n" +
                    "{\n  \"text\": \"string\" , \n  \"needImage\": true|false , \n  \"imagePrompt\": \"string\" \n}\n" +
                    "含义：\n- text: 你的自然语言回答；\n- needImage: 是否需要生成图片；\n- imagePrompt: 当需要图片时，给出适合通义万相的中文图像描述。";

            GenerationParam param = GenerationParam.builder()
                    .apiKey(aiConfig.getDashscope().getApiKey())
                    .model(aiConfig.getDashscope().getChatModel())
                    .messages(java.util.Arrays.asList(
                            Message.builder().role(Role.SYSTEM.getValue()).content(judgeSystem).build(),
                            Message.builder().role(Role.USER.getValue()).content(userInput).build()
                    ))
                    .resultFormat(GenerationParam.ResultFormat.MESSAGE)
                    .build();
            Generation gen = new Generation();
            GenerationResult res = gen.call(param);
            String content = res.getOutput().getChoices().get(0).getMessage().getContent();
            return OBJECT_MAPPER.readValue(content, StructuredReply.class);
        } catch (Exception e) {
            log.warn("[判断是否生成图片] 结构化解析失败，默认不生成: {}", e.getMessage());
            StructuredReply fallback = new StructuredReply();
            fallback.text = null;
            fallback.needImage = false;
            fallback.imagePrompt = null;
            return fallback;
        }
    }

    /**
     * 关闭并删除会话
     * @param chatId 会话ID
     * @return 操作结果
     */
    @DeleteMapping("/close/{id}")
    public BaseResponse<String> closeChatSession(@PathVariable("id") String chatId) {
        return ResultUtils.success("删除成功");
    }
}
